using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using moDb_prototype;
using System.Reflection;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using moDb_prototype.Core;
using moDb_prototype.Serialization;


namespace moDb_prototype
{
    public sealed class ManagedRecord<T> : INullable where T : IManagedRecord<T>, INullable, new()
    {
        private T instance;
        public T Instance
        {
            get { return instance; }
        }
       
        private IDbCommand command;

        private IBinarySerializer<T> createBinarySerializer()
        {
            return new HashTableBinarySerializer<T>(instance);
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            foreach (PropertyInfo prop in Reflector.ReflectedProperties(instance))                
            {
                sb.Append(prop.Name + " = ");
                sb.Append(prop.GetValue(instance, null).ToString());
                sb.Append("|");
            }
            return sb.ToString().TrimEnd('|');
        }

        public bool IsNull
        {
            get
            {
                return instance.IsNull;
            }
        }


        public static T Null
        {
            get
            {
                T nullInstance = new T();
                nullInstance.setNull(true);
                return nullInstance;
            }
        }

        public static T Parse(SqlString sqlString)
        {
            if (sqlString.IsNull)
                return Null;
            T instance = new T();
            foreach (string token in sqlString.ToString().Split('|'))
            {                
                string name = token.Split('=')[0].Trim();
                PropertyInfo prop = Reflector.GetReflectedProperty(instance, name);
                if (prop != null)
                {
                    prop.SetValue(instance, Convert.ChangeType((token.Split('=')[1].Trim()), prop.PropertyType), null);
                }
            }
            return instance;
        }
        
        public ManagedRecord(T instance)
        {
            this.instance = instance;
            command = Database.Connection.CreateCommand();
        }
        
        public void Read(BinaryReader reader)
        {
            IBinarySerializer<T> serializer = createBinarySerializer();
            serializer.Read(reader);            
        }        

        public void Write(BinaryWriter writer)
        {
            IBinarySerializer<T> serializer = createBinarySerializer();
            serializer.Write(writer);            
        }

        public void Save()
        {
            command = Database.Connection.CreateCommand();           
            SqlParameter param = new SqlParameter("@UdtValue", SqlDbType.Udt);
            param.Value = instance;
            param.UdtTypeName = "Person";
            command.Parameters.Add(param);
            command.CommandText = "INSERT INTO dbo.People VALUES (@UDTValue)";
            
            Database.Connection.Open();
            try
            {
                command.ExecuteNonQuery();                
            }
            finally
            {
                Database.Connection.Close();
            }
        }

        public void Load(int id)
        {
        }
    }
}


